home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr49 / vesa18.zip / VESA_PM.C < prev    next >
C/C++ Source or Header  |  1994-12-13  |  22KB  |  604 lines

  1. /* VESA package for emx/gcc --- Copyright (c) 1993 by Johannes Martin */
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5.  
  6. #define INCL_WIN
  7. #define INCL_DOSPROCESS
  8. #define INCL_DOSFILEMGR
  9. #define INCL_DOSQUEUES
  10. #define INCL_DOSSEMAPHORES
  11. #define INCL_DOSMISC
  12. #define INCL_DOSERRORS
  13. #define INCL_DOSSESMGR
  14.  
  15. #include <os2emx.h>
  16. #include <os2thunk.h>
  17.  
  18. #include "vesa.h"
  19. #include "vesadll.h"
  20. #include "common.h"
  21. #include "vesa_pm.h"
  22.  
  23. static VESAWORD _Modes[] = { 0x003, 0x013, 0x100, 0x101, 0x103,
  24.                              0x105, 0x107,
  25.                              0x10F, 0x112, 0x115, 0x118, 0x11b,
  26.                              0xFFFF };
  27.  
  28. static struct _ModeInfo _ModeInfos[] =
  29.     { { 0x1, { 0x0f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  30.                OS2VesaSetWindow, OS2VesaGetWindow, 160,
  31.                640, 400, 8, 16, 1, 4, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  32.       { 0x3, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  33.                OS2VesaSetWindow, OS2VesaGetWindow, 320,
  34.                320, 200, 8,  8, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  35.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  36.                OS2VesaSetWindow, OS2VesaGetWindow, 640,
  37.                640, 400, 8, 16, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  38.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  39.                OS2VesaSetWindow, OS2VesaGetWindow, 640,
  40.                640, 480, 8, 16, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  41.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  42.                OS2VesaSetWindow, OS2VesaGetWindow, 800,
  43.                800, 600, 8, 16, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  44.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  45.                OS2VesaSetWindow, OS2VesaGetWindow, 1024,
  46.                1024, 768, 8, 16, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  47.       { 0xb, { 0x1f, 0x7, 0x0, 2048, 2048, 0x0, 0x0,
  48.                OS2VesaSetWindow, OS2VesaGetWindow, 1280,
  49.                1280, 1024, 8, 16, 1, 8, 1, 0xf4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 } },
  50.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  51.                OS2VesaSetWindow, OS2VesaGetWindow, 960,
  52.                320, 200, 8, 8, 1, 24, 1, 0xf6, 0, 1, 8, 16, 8, 8, 8, 0, 0, 0 } },
  53.       { 0xb, { 0x1f, 0x7, 0x0, 1024, 1024, 0x0, 0x0,
  54.                OS2VesaSetWindow, OS2VesaGetWindow, 1920,
  55.                640, 480, 8, 16, 1, 24, 1, 0xf6, 0, 1, 8, 16, 8, 8, 8, 0, 0, 0 } },
  56.       { 0xb, { 0x1f, 0x7, 0x0, 2048, 2048, 0x0, 0x0,
  57.                OS2VesaSetWindow, OS2VesaGetWindow, 2400,
  58.                800, 600, 8, 16, 1, 24, 1, 0xf6, 0, 1, 8, 16, 8, 8, 8, 0, 0, 0 } },
  59.       { 0xb, { 0x1f, 0x7, 0x0, 4096, 4096, 0x0, 0x0,
  60.                OS2VesaSetWindow, OS2VesaGetWindow, 3072,
  61.                1024, 768, 8, 16, 1, 24, 1, 0xf6, 0, 1, 8, 16, 8, 8, 8, 0, 0, 0 } },
  62.       { 0xb, { 0x1f, 0x7, 0x0, 4096, 4096, 0x0, 0x0,
  63.                OS2VesaSetWindow, OS2VesaGetWindow, 3840,
  64.                1280, 1024, 8, 16, 1, 24, 1, 0xf6, 0, 1, 8, 16, 8, 8, 8, 0, 0, 0 } }
  65.     };
  66.  
  67. static VESAWORD *Modes             = _Modes;
  68. static struct _ModeInfo *ModeInfos = _ModeInfos;
  69.  
  70. static DATABUFFER *DataBuffer;
  71. static HPIPE      hpipe1;
  72. static HPIPE      hpipe2;
  73. static HPIPE      hpipe3;
  74. static HPIPE      hpipe4;
  75.  
  76. static int activeindex   = 0;
  77. static int screenlocked  = 0;
  78.  
  79. static VESACHAR palette[256][3]
  80.    = { {  0,  0,  0 }, {  0,  0, 42 }, {  0, 42,  0 }, {  0, 42, 42 },
  81.        { 42,  0,  0 }, { 42,  0, 42 }, { 42, 21,  0 }, { 42, 42, 42 },
  82.        { 21, 21, 21 }, { 21, 21, 63 }, { 21, 63, 21 }, { 21, 63, 63 },
  83.        { 63, 21, 21 }, { 63, 21, 63 }, { 63, 63, 21 }, { 63, 63, 63 },
  84.        {  0,  0,  0 }, {  5,  5,  5 }, {  8,  8,  8 }, { 11, 11, 11 },
  85.        { 14, 14, 14 }, { 17, 17, 17 }, { 20, 20, 20 }, { 24, 24, 24 },
  86.        { 28, 28, 28 }, { 32, 32, 32 }, { 36, 36, 36 }, { 40, 40, 40 },
  87.        { 45, 45, 45 }, { 50, 50, 50 }, { 56, 56, 56 }, { 63, 63, 63 },
  88.        {  0,  0, 63 }, { 16,  0, 63 }, { 31,  0, 63 }, { 47,  0, 63 },
  89.        { 63,  0, 63 }, { 63,  0, 47 }, { 63,  0, 31 }, { 63,  0, 16 },
  90.        { 63,  0,  0 }, { 63, 16,  0 }, { 63, 31,  0 }, { 63, 47,  0 },
  91.        { 63, 63,  0 }, { 47, 63,  0 }, { 31, 63,  0 }, { 16, 63,  0 },
  92.        {  0, 63,  0 }, {  0, 63, 16 }, {  0, 63, 31 }, {  0, 63, 47 },
  93.        {  0, 63, 63 }, {  0, 47, 63 }, {  0, 31, 63 }, {  0, 16, 63 },
  94.        { 31, 31, 63 }, { 39, 31, 63 }, { 47, 31, 63 }, { 55, 31, 63 },
  95.        { 63, 31, 63 }, { 63, 31, 55 }, { 63, 31, 47 }, { 63, 31, 39 },
  96.        { 63, 31, 31 }, { 63, 39, 31 }, { 63, 47, 31 }, { 63, 55, 31 },
  97.        { 63, 63, 31 }, { 55, 63, 31 }, { 47, 63, 31 }, { 39, 63, 31 },
  98.        { 31, 63, 31 }, { 31, 63, 39 }, { 31, 63, 47 }, { 31, 63, 55 },
  99.        { 31, 63, 63 }, { 31, 55, 63 }, { 31, 47, 63 }, { 31, 39, 63 },
  100.        { 45, 45, 63 }, { 49, 45, 63 }, { 54, 45, 63 }, { 58, 45, 63 },
  101.        { 63, 45, 63 }, { 63, 45, 58 }, { 63, 45, 54 }, { 63, 45, 49 },
  102.        { 63, 45, 45 }, { 63, 49, 45 }, { 63, 54, 45 }, { 63, 58, 45 },
  103.        { 63, 63, 45 }, { 58, 63, 45 }, { 54, 63, 45 }, { 49, 63, 45 },
  104.        { 45, 63, 45 }, { 45, 63, 49 }, { 45, 63, 54 }, { 45, 63, 58 },
  105.        { 45, 63, 63 }, { 45, 58, 63 }, { 45, 54, 63 }, { 45, 49, 63 },
  106.        {  0,  0, 28 }, {  7,  0, 28 }, { 14,  0, 28 }, { 21,  0, 28 },
  107.        { 28,  0, 28 }, { 28,  0, 21 }, { 28,  0, 14 }, { 28,  0,  7 },
  108.        { 28,  0,  0 }, { 28,  7,  0 }, { 28, 14,  0 }, { 28, 21,  0 },
  109.        { 28, 29,  0 }, { 21, 28,  0 }, { 14, 28,  0 }, {  7, 28,  0 },
  110.        {  0, 28,  0 }, {  0, 28,  7 }, {  0, 28, 14 }, {  0, 28, 21 },
  111.        {  0, 28, 28 }, {  0, 21, 28 }, {  0, 14, 28 }, {  0,  7, 28 },
  112.        { 14, 14, 28 }, { 17, 14, 28 }, { 21, 14, 28 }, { 24, 14, 28 },
  113.        { 28, 14, 28 }, { 28, 14, 24 }, { 28, 14, 21 }, { 28, 14, 17 },
  114.        { 28, 14, 14 }, { 28, 17, 14 }, { 28, 21, 14 }, { 28, 24, 14 },
  115.        { 28, 28, 14 }, { 24, 28, 14 }, { 21, 28, 14 }, { 17, 28, 14 },
  116.        { 14, 28, 14 }, { 14, 28, 17 }, { 14, 28, 21 }, { 14, 28, 24 },
  117.        { 14, 28, 28 }, { 14, 24, 28 }, { 14, 21, 28 }, { 14, 17, 28 },
  118.        { 20, 20, 28 }, { 22, 20, 28 }, { 24, 20, 28 }, { 26, 20, 28 },
  119.        { 28, 20, 28 }, { 28, 20, 26 }, { 28, 20, 24 }, { 28, 20, 22 },
  120.        { 28, 20, 20 }, { 28, 22, 20 }, { 28, 24, 20 }, { 28, 26, 20 },
  121.        { 28, 28, 20 }, { 26, 28, 20 }, { 24, 28, 20 }, { 22, 28, 20 },
  122.        { 20, 28, 20 }, { 20, 28, 22 }, { 20, 28, 24 }, { 20, 28, 26 },
  123.        { 20, 28, 28 }, { 20, 26, 28 }, { 20, 24, 28 }, { 20, 22, 28 },
  124.        {  0,  0, 16 }, {  4,  0, 16 }, {  8,  0, 16 }, { 12,  0, 16 },
  125.        { 16,  0, 16 }, { 16,  0, 12 }, { 16,  0,  8 }, { 16,  0,  4 },
  126.        { 16,  0,  0 }, { 16,  4,  0 }, { 16,  8,  0 }, { 16, 12,  0 },
  127.        { 16, 16,  0 }, { 12, 16,  0 }, {  8, 16,  0 }, {  4, 16,  0 },
  128.        {  0, 16,  0 }, {  0, 16,  4 }, {  0, 16,  8 }, {  0, 16, 12 },
  129.        {  0, 16, 16 }, {  0, 12, 16 }, {  0,  8, 16 }, {  0,  4, 16 },
  130.        {  8,  8, 16 }, { 10,  8, 16 }, { 12,  8, 16 }, { 14,  8, 16 },
  131.        { 16,  8, 16 }, { 16,  8, 14 }, { 16,  8, 12 }, { 16,  8, 10 },
  132.        { 16,  8,  8 }, { 16, 10,  8 }, { 16, 12,  8 }, { 16, 14,  8 },
  133.        { 16, 16,  8 }, { 14, 16,  8 }, { 12, 16,  8 }, { 10, 16,  8 },
  134.        {  8, 16,  8 }, {  8, 16, 10 }, {  8, 16, 12 }, {  8, 16, 14 },
  135.        {  8, 16, 16 }, {  8, 14, 16 }, {  8, 12, 16 }, {  8, 10, 16 },
  136.        { 11, 11, 16 }, { 12, 11, 16 }, { 13, 11, 16 }, { 15, 11, 16 },
  137.        { 16, 11, 16 }, { 16, 11, 15 }, { 16, 11, 13 }, { 16, 11, 12 },
  138.        { 16, 11, 11 }, { 16, 12, 11 }, { 16, 13, 11 }, { 16, 15, 11 },
  139.        { 16, 16, 11 }, { 15, 16, 11 }, { 13, 16, 11 }, { 12, 16, 11 },
  140.        { 11, 16, 11 }, { 11, 16, 12 }, { 11, 16, 13 }, { 11, 16, 15 },
  141.        { 11, 16, 16 }, { 11, 15, 16 }, { 11, 13, 16 }, { 11, 12, 16 },
  142.        {  0,  0,  0 }, {  0,  0,  0 }, {  0,  0,  0 }, {  0,  0,  0 },
  143.        {  0,  0,  0 }, {  0,  0,  0 }, {  0,  0,  0 }, {  0,  0,  0 } };
  144.  
  145. VESABOOL OS2VesaSetWindow(VESACHAR Window, VESAWORD Address)
  146. {
  147.   return(TRUE);
  148. }
  149.  
  150. VESABOOL OS2VesaGetWindow(VESACHAR Window, PVESAWORD Address)
  151. {
  152.   *Address = 0;
  153.   return(TRUE);
  154. }
  155.  
  156. VESABOOL OS2VesaGetInfo(PVESAINFO pVesaInfo)
  157. {
  158.   pVesaInfo->Version = 0x102;
  159.   pVesaInfo->OEMName = "OS/2 VESA Driver by Johannes Martin";
  160.   pVesaInfo->Modes   = Modes;
  161.   return(TRUE);
  162. }
  163.  
  164. VESABOOL OS2VesaGetModeInfo(VESAWORD Mode, PVESAMODEINFO pVesaModeInfo)
  165. {
  166.   int i;
  167.  
  168.   Mode &= 0x7fff;
  169.   for (i = 0; Modes[i] != Mode; i++)
  170.     if (Modes[i] == 0xFFFF)
  171.       return(FALSE);
  172.   *pVesaModeInfo = ModeInfos[i].Vesa;
  173.   pVesaModeInfo->WindowAStart = DataBuffer->GraphBuffer;
  174.   pVesaModeInfo->WindowBStart = DataBuffer->GraphBuffer;
  175.   return(TRUE);
  176. }
  177.  
  178. VESABOOL OS2VesaSetMode(VESAWORD Mode)
  179. {
  180.   ULONG count;
  181.  
  182.   DosResetEventSem(DataBuffer->hev, &count);
  183.   WinPostMsg(DataBuffer->hwndGraph, WM_DONTUPDATE, NULL, NULL);
  184.   for (activeindex = 0; Modes[activeindex] != Mode & 0x7fff; activeindex++)
  185.     if (Modes[activeindex] == 0xFFFF)
  186.       {
  187.         activeindex = 0;
  188.         break;
  189.       }
  190.   DosWaitEventSem(DataBuffer->hev, SEM_INDEFINITE_WAIT);
  191.   if (DataBuffer->GraphBuffer != NULL)
  192.     DosFreeMem(DataBuffer->GraphBuffer);
  193.   if (activeindex)
  194.     DosAllocSharedMem(&DataBuffer->GraphBuffer, NULL,
  195.                       ModeInfos[activeindex].Vesa.Width
  196.                       * ModeInfos[activeindex].Vesa.Height
  197.                       * ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel / 8,
  198.                       OBJ_GETTABLE | PAG_READ | PAG_WRITE | PAG_COMMIT);
  199.   else
  200.     DataBuffer->GraphBuffer = NULL;
  201.   DataBuffer->pointl[2].x = 0;
  202.   DataBuffer->pointl[2].y = 0;
  203.   DataBuffer->pointl[3].x = ModeInfos[activeindex].Vesa.Width;
  204.   DataBuffer->pointl[3].y = ModeInfos[activeindex].Vesa.Height;
  205.   if ((DataBuffer->bits = ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel) <= 8)
  206.     OS2VesaSetPalette(0, 1 << ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel,
  207.                       (PVESACHAR) palette, 0);
  208.   WinPostMsg(DataBuffer->hwndGraph, WM_NEWMODE, NULL, NULL);
  209.   return(activeindex != 0);
  210. }
  211.  
  212. VESABOOL OS2VesaGetMode(PVESAWORD Mode)
  213. {
  214.   *Mode = Modes[activeindex];
  215.   return(TRUE);
  216. }
  217.  
  218. VESABOOL OS2VesaSetScanlineLength(VESAWORD NumberOfPixels)
  219. {
  220.   return(NumberOfPixels == ModeInfos[activeindex].Vesa.BytesPerScanline * 8 /
  221.                            ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel);
  222. }
  223.  
  224. VESABOOL OS2VesaGetScanlineLength(PVESAWORD BytesPerScanline,
  225.                                   PVESAWORD NumberOfPixels,
  226.                                   PVESAWORD NumberOfScanlines)
  227. {
  228.   *BytesPerScanline *= ModeInfos[activeindex].Vesa.BytesPerScanline;
  229.   *NumberOfPixels    = ModeInfos[activeindex].Vesa.Width;
  230.   *NumberOfScanlines = ModeInfos[activeindex].Vesa.Height;
  231.   return(TRUE);
  232. }
  233.  
  234. VESABOOL OS2VesaSetSwitchFunc(VESASWITCH SwitchFunc)
  235. {
  236.   return(TRUE);
  237. }
  238.  
  239. VESABOOL OS2VesaLockScreen(VESACHAR wait)
  240. {
  241.   if (screenlocked == 0)
  242.     {
  243.       ULONG count;
  244.  
  245.       DosResetEventSem(DataBuffer->hev, &count);
  246.       WinPostMsg(DataBuffer->hwndGraph, WM_DONTUPDATE, NULL, NULL);
  247.       DosWaitEventSem(DataBuffer->hev, SEM_INDEFINITE_WAIT);
  248.     }
  249.   screenlocked++;
  250.   return(TRUE);
  251. }
  252.  
  253. VESABOOL OS2VesaUnlockScreen(void)
  254. {
  255.   if (screenlocked)
  256.     {
  257.       screenlocked--;
  258.       if (screenlocked == 0)
  259.         WinPostMsg(DataBuffer->hwndGraph, WM_UPDATE, NULL, NULL);
  260.       return(TRUE);
  261.     }
  262.   else
  263.     return(FALSE);
  264. }
  265.  
  266. VESABOOL OS2VesaSetModified(void)
  267. {
  268.   DataBuffer->modified = TRUE;
  269.   return(TRUE);
  270. }
  271.  
  272. VESABOOL OS2VesaSetPalette(VESAWORD   StartIndex,
  273.                            VESAWORD   NumberOfEntries,
  274.                            PCVESACHAR Palette,
  275.                            VESABOOL   Wait)
  276. {
  277.   if ((ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel <= 8) &&
  278.       (NumberOfEntries >= 1) &&
  279.       (StartIndex + NumberOfEntries <= 1 << ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel))
  280.     {
  281.       int   i;
  282.       RGB2  *pal_entry;
  283.       ULONG count;
  284.  
  285.       pal_entry = &DataBuffer->bmi.argbColor[StartIndex];
  286.       for (i = 0; i < NumberOfEntries; i++)
  287.         {
  288.           pal_entry->bRed      = Palette[i * 3 + 0] << 2;
  289.           pal_entry->bGreen    = Palette[i * 3 + 1] << 2;
  290.           pal_entry->bBlue     = Palette[i * 3 + 2] << 2;
  291.           pal_entry->fcOptions = 0;
  292.           pal_entry++;
  293.         }
  294.       DosResetEventSem(DataBuffer->hev, &count);
  295.       WinPostMsg(DataBuffer->hwndGraph, WM_CHGPALETTE, NULL, NULL);
  296.       DosWaitEventSem(DataBuffer->hev, SEM_INDEFINITE_WAIT);
  297.       return(TRUE);
  298.     }
  299.   return(FALSE);
  300. }
  301.  
  302. VESABOOL OS2VesaGetPalette(VESAWORD  StartIndex,
  303.                            VESAWORD  NumberOfEntries,
  304.                            PVESACHAR Palette)
  305. {
  306.   if ((ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel <= 8) &&
  307.       (NumberOfEntries >= 1) &&
  308.       (StartIndex + NumberOfEntries <= 1 << ModeInfos[activeindex].Vesa.NumberOfBitsPerPixel))
  309.     {
  310.       int i;
  311.       RGB2 *pal_entry;
  312.  
  313.       pal_entry = &DataBuffer->bmi.argbColor[StartIndex];
  314.       for (i = 0; i < NumberOfEntries; i++)
  315.         {
  316.           Palette[i * 3 + 0] = pal_entry->bRed   >> 2;
  317.           Palette[i * 3 + 1] = pal_entry->bGreen >> 2;
  318.           Palette[i * 3 + 2] = pal_entry->bBlue  >> 2;
  319.           pal_entry++;
  320.         }
  321.       return(TRUE);
  322.     }
  323.   return(FALSE);
  324. }
  325.  
  326. VESABOOL OS2VesaGetCharacter(PVESACHAR pchar)
  327. {
  328.   ULONG read;
  329.  
  330.   DosRead(hpipe2, pchar, sizeof(VESACHAR), &read);
  331.   return(read == sizeof(VESACHAR));
  332. }
  333.  
  334. VESABOOL OS2VesaKeyboardHit(void)
  335. {
  336.   VESACHAR  byte;
  337.   ULONG     read, status;
  338.   AVAILDATA avail;
  339.  
  340.   DosPeekNPipe(hpipe2, &byte, sizeof(VESACHAR), &read, &avail, &status);
  341.   return(read == sizeof(VESACHAR));
  342. }
  343.  
  344. VESABOOL OS2MouseOpen(void)
  345. {
  346.   return(TRUE);
  347. }
  348.  
  349. VESABOOL OS2MouseClose(void)
  350. {
  351.   return(TRUE);
  352. }
  353.  
  354. VESABOOL OS2MouseShow(void)
  355. {
  356.   return(TRUE);
  357. }
  358.  
  359. VESABOOL OS2MouseHide(void)
  360. {
  361.   return(TRUE);
  362. }
  363.  
  364. VESABOOL OS2MouseSetPosition(VESAWORD x, VESAWORD y)
  365. {
  366.   WinPostMsg(DataBuffer->hwndGraph, WM_SETMOUSEPOS, MPFROM2SHORT(x, y), NULL);
  367.   return(FALSE);
  368. }
  369.  
  370. VESABOOL OS2MouseGetPosition(PVESAWORD x, PVESAWORD y)
  371. {
  372.   *x = DataBuffer->mousex;
  373.   *y = DataBuffer->mousey;
  374.   return(TRUE);
  375. }
  376.  
  377. VESABOOL OS2MouseGetEvent(PVESAWORD x, PVESAWORD y, PVESAWORD status, VESABOOL wait)
  378. {
  379.   *x      = DataBuffer->mousex;
  380.   *y      = DataBuffer->mousey;
  381.   *status = DataBuffer->mousestatus;
  382.   return(FALSE);
  383. }
  384.  
  385. int readdec(PCSZ *s)
  386. {
  387.   int i;
  388.  
  389.   i = 0;
  390.   while ((**s >= '0') && (**s <= '9'))
  391.     {
  392.       i = i * 10 + **s - '0';
  393.       ++*s;
  394.     }
  395.   return(i);
  396. }
  397.  
  398. int readhex(PCSZ *s)
  399. {
  400.   int i;
  401.  
  402.   i = 0;
  403.   while (TRUE)
  404.     {
  405.       if ((**s >= '0') && (**s <= '9'))
  406.         i = i * 16 + **s - '0';
  407.       else if ((**s >= 'A') && (**s <= 'F'))
  408.         i = i * 16 + **s - 'A' + 10;
  409.       else if ((**s >= 'a') && (**s <= 'f'))
  410.         i = i * 16 + **s - 'a' + 10;
  411.       else
  412.         break;
  413.       ++*s;
  414.     }
  415.   return(i);
  416. }
  417.  
  418. int BuildModeTable(void)
  419. {
  420.   PCSZ s;
  421.  
  422.   if (DosScanEnv("PMSCRMOD", &s) == 0)
  423.     {
  424.       int i;
  425.       PCSZ d;
  426.  
  427.       i = 0;
  428.       d = s;
  429.       while (*d != '\0')
  430.         if (*d++ == ';')
  431.           i++;
  432.       if (DosAllocMem((PPVOID) &Modes, (i + 3) * sizeof(VESAWORD) +
  433.                                        (i + 2) * sizeof(struct _ModeInfo),
  434.                                        PAG_READ | PAG_WRITE | PAG_COMMIT))
  435.         return(FALSE);
  436.       ModeInfos = (void *) &Modes[i + 3];
  437.       Modes[0]  = _Modes[0];
  438.       memcpy(&ModeInfos[0], &_ModeInfos[0], sizeof(struct _ModeInfo));
  439.       i = 1;
  440.       while (*s != '\0')
  441.         {
  442.           int x, y, c;
  443.  
  444.           Modes[i] = readhex(&s);
  445.           if ((*s != ',') || (Modes[i] == 0x3) || (Modes[i] == 0xFFFF))
  446.             return(FALSE);
  447.           s++;
  448.           x = readdec(&s);
  449.           if ((*s != ',') || (x <= 0) || (x >= 32768))
  450.             return(FALSE);
  451.           s++;
  452.           y = readdec(&s);
  453.           if ((*s != ',') || (y <= 0) || (y >= 32768))
  454.             return(FALSE);
  455.           s++;
  456.           c = readdec(&s);
  457.           switch (c)
  458.             {
  459.               case 8:
  460.                 memcpy(&ModeInfos[i], &_ModeInfos[2], sizeof(struct _ModeInfo));
  461.                 break;
  462.               case 24:
  463.                 memcpy(&ModeInfos[i], &_ModeInfos[7], sizeof(struct _ModeInfo));
  464.                 break;
  465.               default:
  466.                 return(FALSE);
  467.             }
  468.           ModeInfos[i].Vesa.WindowGranularity = (x * y * c / 8 + 1023) / 1024;
  469.           ModeInfos[i].Vesa.WindowSize        = ModeInfos[i].Vesa.WindowGranularity;
  470.           ModeInfos[i].Vesa.BytesPerScanline  = x * c / 8;
  471.           ModeInfos[i].Vesa.Width             = x;
  472.           ModeInfos[i].Vesa.Height            = y;
  473.           if ((*s != ';') && (*s != '\0'))
  474.             return(FALSE);
  475.           s++;
  476.           i++;
  477.         }
  478.       Modes[i] = 0xFFFF;
  479.     }
  480.   return(TRUE);
  481. }
  482.  
  483. int _CRT_init(void);
  484. void _CRT_term(void);
  485.  
  486. unsigned long _DLL_InitTerm(unsigned long modhandle, unsigned long flag)
  487. {
  488.   ULONG count;
  489.  
  490.   if (!flag)
  491.     {
  492.       STARTDATA StartData;
  493.       char  params[20], prgname[256], *c, *d;
  494.       ULONG sid, rc;
  495.       PID   pid;
  496.       HFILE std;
  497.       PPIB  ppib;
  498.       PTIB  ptib;
  499.  
  500.       if (_CRT_init())
  501.         return(FALSE);
  502.       if (!BuildModeTable())
  503.         {
  504.           static char message[] = "Invalid mode description in environment variable PMSCRMOD.\r\n";
  505.           ULONG written;
  506.  
  507.           DosWrite(2, message, strlen(message), &written);
  508.           if (Modes != _Modes)
  509.             DosFreeMem((PVOID) Modes);
  510.           return(FALSE);
  511.         }
  512.       DosAllocSharedMem((PPVOID) &DataBuffer, NULL, sizeof(DATABUFFER),
  513.                         OBJ_GETTABLE | PAG_READ | PAG_WRITE | PAG_COMMIT);
  514.       memset(DataBuffer, 0, sizeof(DATABUFFER));
  515.       DosCreateEventSem(NULL, &DataBuffer->hev, DC_SEM_SHARED, 0);
  516.       DosGetInfoBlocks(&ptib, &ppib);
  517.       strcpy(DataBuffer->Pipe1Name, "\\PIPE\\VESA_PM1.");
  518.       _itoa(ppib->pib_ulpid, DataBuffer->Pipe1Name + 15, 16);
  519.       strcpy(DataBuffer->Pipe2Name, DataBuffer->Pipe1Name);
  520.       DataBuffer->Pipe2Name[14] = '2';
  521.       strcpy(DataBuffer->Pipe3Name, DataBuffer->Pipe1Name);
  522.       DataBuffer->Pipe3Name[14] = '3';
  523.       strcpy(DataBuffer->Pipe4Name, DataBuffer->Pipe1Name);
  524.       DataBuffer->Pipe4Name[14] = '4';
  525.       c = ppib->pib_pchenv;
  526.       while (*c != '\0')
  527.         c += strlen(c) + 1;
  528.       if ((d = strrchr(++c, '\\')) != NULL)
  529.         c = d + 1;
  530.       strncpy(DataBuffer->ProgName, c, sizeof(DataBuffer->ProgName) - 1);
  531.       DataBuffer->ProgName[sizeof(DataBuffer->ProgName) - 1] = '\0';
  532.       DosCreateNPipe(DataBuffer->Pipe1Name, &hpipe1, NP_ACCESS_INBOUND, 1, 0, 256, 0);
  533.       DosCreateNPipe(DataBuffer->Pipe2Name, &hpipe2, NP_ACCESS_INBOUND, 1, 0, 256, 0);
  534.       DosCreateNPipe(DataBuffer->Pipe3Name, &hpipe3, NP_ACCESS_OUTBOUND, 1, 256, 0, 0);
  535.       DosCreateNPipe(DataBuffer->Pipe4Name, &hpipe4, NP_ACCESS_OUTBOUND, 1, 256, 0, 0);
  536.       memset(&StartData, 0, sizeof(StartData));
  537.       StartData.Length      = sizeof(StartData);
  538.       StartData.Related     = 0;
  539.       StartData.FgBg        = 0;
  540.       StartData.TraceOpt    = 0;
  541.       StartData.PgmTitle    = NULL;
  542.       if (DosScanEnv("PMSCREEN", (PCSZ *) &StartData.PgmName))
  543.         {
  544.           if (DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT | SEARCH_CUR_DIRECTORY,
  545.                             "PATH", "PMSCREEN.EXE", prgname, sizeof(prgname)))
  546.             StartData.PgmName = "PMSCREEN.EXE";
  547.           else
  548.             StartData.PgmName = prgname;
  549.         }
  550.       StartData.PgmInputs   = _itoa((ULONG) DataBuffer, params, 10);
  551.       StartData.TermQ       = NULL;
  552.       StartData.Environment = NULL;
  553.       StartData.InheritOpt  = 1;
  554.       StartData.SessionType = SSF_TYPE_PM;
  555.       StartData.IconFile    = 0;
  556.       StartData.PgmHandle   = 0;
  557.       if (((rc = DosStartSession(&StartData, &sid, &pid)) != 0) &&
  558.           (rc != ERROR_SMG_START_IN_BACKGROUND))
  559.         {
  560.           static char message[] = " not found.\r\n";
  561.           ULONG written;
  562.  
  563.           DosWrite(2, StartData.PgmName, strlen(StartData.PgmName), &written);
  564.           DosWrite(2, message, strlen(message), &written);
  565.           return(FALSE);
  566.         }
  567.       DosWaitEventSem(DataBuffer->hev, SEM_INDEFINITE_WAIT);
  568.       DosConnectNPipe(hpipe1);
  569.       DosConnectNPipe(hpipe2);
  570.       DosConnectNPipe(hpipe3);
  571.       DosConnectNPipe(hpipe4);
  572.       std = 0;
  573.       DosDupHandle(hpipe1, &std);
  574.       std = 1;
  575.       DosDupHandle(hpipe3, &std);
  576.       std = 2;
  577.       DosDupHandle(hpipe4, &std);
  578.       OS2VesaSetMode(0);
  579.       return(TRUE);
  580.     }
  581.   if (DataBuffer->hwndGraph != 0)
  582.     {
  583.       DosResetEventSem(DataBuffer->hev, &count);
  584.       WinPostMsg(DataBuffer->hwndGraph, WM_FINISH, NULL, NULL);
  585.       DosWaitEventSem(DataBuffer->hev, 10000);
  586.     }
  587.   DosCloseEventSem(DataBuffer->hev);
  588.   DosDisConnectNPipe(hpipe1);
  589.   DosDisConnectNPipe(hpipe2);
  590.   DosDisConnectNPipe(hpipe3);
  591.   DosDisConnectNPipe(hpipe4);
  592.   DosClose(hpipe1);
  593.   DosClose(hpipe2);
  594.   DosClose(hpipe3);
  595.   DosClose(hpipe4);
  596.   if (DataBuffer->GraphBuffer != NULL)
  597.     DosFreeMem(DataBuffer->GraphBuffer);
  598.   DosFreeMem(DataBuffer);
  599.   if (Modes != _Modes)
  600.     DosFreeMem((PVOID) Modes);
  601.   _CRT_term();
  602.   return(TRUE);
  603. }
  604.